package com.ray.tool;


import com.ray.tool.common.constant.RayDateConstants;
import com.ray.tool.date.RayDateTools;
import com.ray.tool.common.enums.RayLogLevelEnum;
import com.ray.tool.common.enums.ConsoleColorEnum;

import java.util.Date;

/**
 * 控制台输出 - 工具类
 * 提供给用户
 * 仅依赖于JDK8
 *
 * @author LiaoYuXing-Ray
 * @version 1.0
 * @createDate 2023/8/29 15:36
 **/
@SuppressWarnings("unused")
public class RayConsole {

    /**
     * 工具类中的方法都是静态方法访问的，因此将构造器私有不允许创建对象
     *
     * @author LiaoYuXing-Ray 2023/9/7 10:24
     */
    private RayConsole() {
        throw new AssertionError();
    }

    /**
     * 控制台日志 - DIY款
     * 可接受自定义输出款式
     *
     * @param args 输出参数
     * @author LiaoYuXing-Ray 2023/9/15 17:54
     **/
    public static void info(Object... args) {
        rayPrintMessage(RayLogLevelEnum.INFO, ConsoleColorEnum.WHITE, args);
    }

    /**
     * 控制台日志 - DIY款
     * 可接受自定义输出款式
     *
     * @param args 输出参数
     * @author LiaoYuXing-Ray 2023/9/15 17:54
     **/
    public static void debug(Object... args) {
        rayPrintMessage(RayLogLevelEnum.DEBUG, ConsoleColorEnum.BLACK, args);
    }

    /**
     * 控制台日志 - DIY款
     * 可接受自定义输出款式
     *
     * @param args 输出参数
     * @author LiaoYuXing-Ray 2023/9/15 17:54
     **/
    public static void warn(Object... args) {
        rayPrintMessage(RayLogLevelEnum.WARN, ConsoleColorEnum.YELLOW, args);
    }

    /**
     * 控制台日志 - DIY款
     * 可接受自定义输出款式
     *
     * @param args 输出参数
     * @author LiaoYuXing-Ray 2023/9/15 17:54
     **/
    public static void error(Object... args) {
        rayPrintMessage(RayLogLevelEnum.ERROR, ConsoleColorEnum.RED, args);
    }

    /**
     * 控制台日志 - 简约款
     * 单纯输出日志
     *
     * @param args 输出参数
     * @author LiaoYuXing-Ray 2023/9/15 17:54
     **/
    public static void out(Object... args) {
        System.out.println(printMessage(args));
    }

    /**
     * 控制台日志 - 简约款
     * 单纯输出日志（红色）
     *
     * @param args 输出参数
     * @author LiaoYuXing-Ray 2023/9/15 17:54
     **/
    public static void err(Object... args) {
        System.err.println(printMessage(args));
    }

    /**
     * 输出信息，多个参数会以制表位分开-简约款 - 私有
     *
     * @param args 参数
     * @author LiaoYuXing-Ray 2023/9/14 15:04
     */
    private static StringBuilder printMessage(Object... args) {
        StringBuilder sb = new StringBuilder();
        if (args != null && args.length >= 1) {
            sb.append("[").append(RayDateTools.getNowTime()).append("]");
            sb.append(" ");
            connectArgs(sb, args);
        }
        return sb;
    }


    /**
     * 输出信息，多个参数会以制表位分开-DIY款 - 私有
     *
     * @param args 参数
     * @author LiaoYuXing-Ray 2023/9/14 15:04
     */
    private static void rayPrintMessage(RayLogLevelEnum type, ConsoleColorEnum color, Object... args) {
        // args不为空且args的长度大于等于1
        if (args != null && args.length >= 1) {
            StringBuilder sb = new StringBuilder();
            sb.append(RayDateTools.getNowTime());
            sb.append(" ");
            switch (type) {
                case INFO:
                    sb.append("\033[32m")
                            .append(RayLogLevelEnum.INFO.getDesc()).append("\033[0m");
                    sb.append(" ");
                    break;
                case DEBUG:
                    sb.append("\033[30m")
                            .append(RayLogLevelEnum.DEBUG.getDesc()).append("\033[0m");
                    break;
                case WARN:
                    sb.append("\033[33m")
                            .append(RayLogLevelEnum.WARN.getDesc()).append("\033[0m");
                    sb.append(" ");
                    break;
                case ERROR:
                    sb.append("\033[31m")
                            .append(RayLogLevelEnum.ERROR.getDesc()).append("\033[0m");
                    break;
                default:
                    System.out.println("未知的日志级别");
                    break;
            }
            sb.append(" ");
            sb.append("\033[35m").append(RayTools.getCurrentPID()).append("\033[0m");
            sb.append(" --- ");
            sb.append("[").append(Thread.currentThread().getName()).append("]").append(" ");
            // 自定义输出颜色
            sb.append("\033[").append(color.getIndex()).append("m");
            // 输出传入参数
            connectArgs(sb, args);
            sb.append("\033[0m"); // 重置
            System.out.println(sb);
        }
    }


    /**
     * 拼接传入参数，多个参数用\t分隔 - 私有
     *
     * @param sb   拼接的字符串
     * @param args 拼接参数
     * @author LiaoYuXing-Ray 2023/9/15 17:52
     **/
    private static void connectArgs(StringBuilder sb, Object... args) {
        for (Object arg : args) {
            if (arg instanceof Date) {
                sb.append(RayDateTools.getStringDate(new Date()));
            } else if (arg instanceof Double) {
                sb.append(RayDateConstants.DECIMAL_FOR_MAT.format(Double.parseDouble(arg.toString())));
            } else if (arg == null) {
                sb.append(" null ");
            } else {
                sb.append(arg);
            }
            sb.append("\t");
        }
    }

    /*
        在Java中，可以使用ANSI转义序列来在控制台输出带有颜色的文本。
        这些序列是一种特殊的字符序列，可以改变终端文本的颜色和样式。
        以下是一些基本的ANSI转义序列：
        \033[0m：重置所有属性
        \033[1m：设置高亮度
        \033[4m：下划线
        \033[5m：闪烁
        \033[7m：反显
        \033[30m - \033[37m：设置前景色（30-37）
        \033[40m - \033[47m：设置背景色（40-47）
        30: 黑色 black    BLACK
        31: 红色 red      RED
        32: 绿色 green    GREEN
        33: 黄色 yellow   YELLOW
        34: 蓝色 blue     BLUE
        35: 紫色 purple   PURPLE
        36: 青色 cyan     CYAN
        37: 白色 white    WHITE
    */

}
